home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Mathematics / Notebooks / SigProc2.0 / Packages / SignalProcessing / Support / SupCode.m < prev    next >
Encoding:
Text File  |  1992-08-18  |  41.2 KB  |  1,365 lines

  1. (*  :Title:    Supporting Routines  *)
  2.  
  3. (*  :Authors:    Brian Evans, James McClellan  *)
  4.  
  5. (*
  6.     :Summary:    To provide routines that Mathematica should have.
  7.         Many are borrowed from Lisp.
  8.  *)
  9.  
  10. (*  :Context:    SignalProcessing`Support`SupCode`  *)
  11.  
  12. (*  :PackageVersion:  2.7    *)
  13.  
  14. (*
  15.     :Copyright:    Copyright 1989-1991 by Brian L. Evans
  16.         Georgia Tech Research Corporation
  17.  
  18.     Permission to use, copy, modify, and distribute this software
  19.     and its documentation for any purpose and without fee is
  20.     hereby granted, provided that the above copyright notice
  21.     appear in all copies and that both that copyright notice and
  22.     this permission notice appear in supporting documentation,
  23.     and that the name of the Georgia Tech Research Corporation,
  24.     Georgia Tech, or Georgia Institute of Technology not be used
  25.     in advertising or publicity pertaining to distribution of the
  26.     software without specific, written prior permission.  Georgia
  27.     Tech makes no representations about the suitability of this
  28.     software for any purpose.  It is provided "as is" without
  29.     express or implied warranty.
  30.  *)
  31.  
  32. (*  :History:    *)
  33.  
  34. (*  :Keywords:    list processing, sequences, number theory, set theory    *)
  35.  
  36. (*  :Source:    *)
  37.  
  38. (*  :Warning:    *)
  39.  
  40. (*  :Mathematica Version:  1.2 or 2.0  *)
  41.  
  42. (*  :Limitation:  *)
  43.  
  44. (*
  45.     :Functions:    AllSubsets
  46.         Arrow2D
  47.         AssociateItem
  48.         Assuming
  49.         CirclePS
  50.         Combine
  51.         ComplexQ
  52.         ComplexTo2DCoord
  53.         ComplexTo2DCoordList
  54.         ConstantQ
  55.         ConstantTerm
  56.         Dialogue
  57.         Element
  58.         EmptyQ
  59.         GenerateCode
  60.         GeneratePattern
  61.         GenerateSymbol
  62.         GetAllExponents
  63.         GetAllFactors
  64.         GetAllShiftFactors
  65.         GetArgs
  66.         GetRoot
  67.         GetRootList
  68.         GetShiftFactor
  69.         GetStateField
  70.         GetVariables
  71.         GetValue
  72.         HasAttributes
  73.         ImaginaryQ
  74.         InRange
  75.         InfinityQ
  76.         InformUserQ
  77.         ListQ
  78.         MixedPolynomialQ
  79.         MyApart
  80.         MyCollectAll
  81.         MyFreeQ
  82.         MyMessage
  83.         PatternQ
  84.         PointwisePlot
  85.         PrintIt
  86.         ProtectIt
  87.         RationalQ
  88.         RationalFunctionQ
  89.         RationalPolynomialQ
  90.         RealQ
  91.         RealValuedQ
  92.         RemoveOptions
  93.         ReplaceWith
  94.         RuleAppliesQ
  95.         SameFormQ
  96.         Second
  97.         SetExclusion
  98.         SetStateField
  99.         StripPackage
  100.         SubsetQ
  101.         TableLookup
  102.         Third
  103.         ToCollection
  104.         ToList
  105.         UnprotectIt
  106.         VariableQ
  107.         ZeroQ
  108.         ZPolynomial
  109.  *)
  110.  
  111.  
  112. If [ ! TrueQ[ $VersionNumber >= 2.0 ],
  113.      $Packages := $ContextPath;
  114.      $Packages::usage =
  115.     "$Packages gives a list of the contexts corresponding to all packages \
  116.     which have been loaded in your current Mathematica session.";
  117.      Protect[$Packages] ]
  118.  
  119. $loaded = MemberQ[ $Packages, "SignalProcessing`Support`SupCode`" ]
  120.  
  121. If [ TrueQ[ $VersionNumber >= 2.0 ],
  122.      Unprotect[ ListQ ];
  123.      Clear[ ListQ ];
  124.      $NewMessage[ System`Set, "wrsym" ];
  125.      $NewMessage[ System`SetDelayed, "write" ];
  126.      Off[ Set::wrsym ];
  127.      Off[ SetDelayed::write ];
  128.      $NewMessage[ System`General, "spell" ];
  129.      $NewMessage[ System`General, "spell1" ];
  130.      Off[ General::spell ];
  131.      Off[ General::spell1 ] ]
  132.  
  133.  
  134. (*  B E G I N     P A C K A G E  *)
  135.  
  136. BeginPackage[ "SignalProcessing`Support`SupCode`" ]
  137.  
  138.  
  139. (*  U S A G E     I N F O R M A T I O N  *)
  140.  
  141. AllSubsets::usage =
  142.     "AllSubsets[set] returns a list of all subsets of set, \
  143.     including the null set {}. \
  144.     The original set must be a lis."
  145.  
  146. Arrow2D::usage =
  147.     "Arrow2D[tail, plotwidth, plotheight] returns a graphics object \
  148.     that is an arrow starting at tail, pointing upwards, of \
  149.     length plotheight. \
  150.     The length of the tail and the direction of the arrow are controlled \
  151.     by an optional fourth parameter."
  152.  
  153. AssociateItem::usage =
  154.     "AssociateItem[item, lookuplist, newlist] finds the location of \
  155.     item in the lookuplist and returns the element of newlist in \
  156.     that position. \
  157.     If item is not is lookup list, Null is returned. \
  158.     If item is a list, then a list of associations is returned."
  159.  
  160. Assuming::usage =
  161.     "Assuming[condition] keeps track of assumptions made during \
  162.     a calculation. \
  163.     Assuming[All] gives all of the current assumptions. \
  164.     Assuming[condition, True] prints the condition if it is not True. \
  165.     Assuming[] removes all current assumptions."
  166.  
  167. CirclePS::usage =
  168.     "CirclePS[r] and CirclePS[r, p] will return a graphics object, \
  169.     a circle of radius r with plotstyle p. \
  170.     CirclePS makes use of the Circle primitive."
  171.  
  172. Combine::usage =
  173.     "Combine[object, joindata] sets the value of object to the \
  174.     joining of object with joindata; however, if object has no \
  175.     value, then object is set to joindata."
  176.  
  177. ComplexQ::usage =
  178.     "ComplexQ[z] returns True if z is a complex number, False otherwise."
  179.  
  180. ComplexTo2DCoord::usage =
  181.     "ComplexTo2DCoord[x] returns the two-dimensional coordinate \
  182.     corresponding to the complex form of x. \
  183.     That is, a pair of values in the form { Re[x], Im[x] } is returned."
  184.  
  185. ComplexTo2DCoordList::usage =
  186.     "ComplexTo2DCoordList[zlist] returns a list of coordinates \
  187.     corresponding to the complex form of each element in zlist. \
  188.     That is, zlist is mapped through ComplexTo2DCoord."
  189.  
  190. ConstantQ::usage =
  191.     "ConstantQ[x] returns True if x is always constant. \
  192.     If x is an atom, then x is constant it is a number or it x has \
  193.     a Constant attribute. \
  194.     If x is a function of the form f[arg1, arg2, ...], then x is \
  195.     considered to be constant if arg1, arg2, ..., are constant."
  196.  
  197. ConstantTerm::usage =
  198.     "ConstantTerm[expr, x] returns the constant term of the \
  199.     expression expr."
  200.  
  201. Dialogue::usage =
  202.     "Dialogue is an option for all of the symbolic transforms, the \
  203.     differential/difference equations solvers, and more. \
  204.     Possible settings are False, True, or All, for no, partial, or \
  205.     full justification, respectively. \
  206.     In the case of symbolic transforms, a setting of True or All will \
  207.     cause the rule base to describe strategies being applied to compute \
  208.     the transform as well as the functions (if any) which it could not \
  209.     transform. \
  210.     If it set to All, then the rule base will also display each step \
  211.     of the transform reasoning."
  212.  
  213. Element::usage =
  214.     "Element[expr, n] returns the nth element of expr if n is an integer \
  215.     or list of integers. \
  216.     Element[expr, n1, n2, ..., nm] returns expr[[n1, n2,..., nm]] if \
  217.     n1, n2, ... nm are integers."
  218.  
  219. EmptyQ::usage =
  220.     "EmptyQ[packet] returns True the packet of data is empty."
  221.  
  222. GenerateCode::usage =
  223.     "GenerateCode[object] converts object to a string (if necessary) \
  224.     and then evaluates it (translates it to Mathematica code)."
  225.  
  226. GeneratePattern::usage =
  227.     "GeneratePattern[namestring] generates a symbol with the name \
  228.     equal to namestring followed by an underscore, which makes the \
  229.     object be a pattern which can be used for pattern matching. \
  230.     For example, GeneratePattern[\"a\"] yields the pattern (a_)."
  231.  
  232. GenerateSymbol::usage =
  233.     "GenerateSymbol[namestring], GenerateSymbol[namestring, trailer], \
  234.     and GenerateSymbol[namestring, trailer, header], generate a \
  235.     symbol by concatenating header, namestring, and trailer."
  236.  
  237. GetAllExponents::usage =
  238.     "GetAllExponents[expr, x] returns all exponents of the \
  239.     term x in the expression expr. \
  240.     GetAllExponents[z^3 + 2 z^6, z] returns {6, 3}."
  241.  
  242. GetAllFactors::usage =
  243.     "GetAllFactors[expr, x] returns all factors of the \
  244.     term x in the expression expr. \
  245.     GetAllFactors[z^3 + 2 z^6, z] returns {1, 2}. \
  246.     GetAllFactors[z^-3 + 2 z^-6, z] returns {1/2, 1}."
  247.  
  248. GetAllShiftFactors::usage =
  249.     "GetAllShiftFactors[expr, x] returns a list containing all \
  250.     shift factors in the variable x. \
  251.     The expression is traversed as is using a depth-first search. \
  252.     For example, GetAllShiftFactors[ (2 s + 2 b + c) Exp[s + b + Pi], s] \
  253.     returns { b + Pi, (2 b + c)/2 }."
  254.  
  255. GetArgs::usage =
  256.     "GetArgs[function] returns the argument(s) of the function. \
  257.     For example, GetArgs[ Bogus[1,2,3] ] would return 1,2,3. \
  258.     If the programmer only wishes to replace the head of a function \
  259.     with another, then use Apply instead of GetArgs. \
  260.     This function is similar to ToCollection."
  261.  
  262. GetOperatorVariables::usage =
  263.     "GetOperatorVariables[op] returns the variable(s) in the \
  264.     parameterized operator op. \
  265.     By default, GetOperatorVariables[ op[par1, par2, ...] ] \
  266.     returns the first parameter, par1."
  267.  
  268. GetRoot::usage =
  269.     "GetRoot[rule] extracts the value from an expression like \
  270.     {z -> 0.}, which is 0. in this case."
  271.  
  272. GetRootList::usage =
  273.     "GetRootList[p, x] returns a list of the approximate numerical roots \
  274.     of expression p, a function of x, with infinite roots removed. \ 
  275.     GetRootList[p, x, filter] applies filter to the list of roots \
  276.     returned by the Solve function (defaults to N). \
  277.     When GetRootList cannot find a set of roots, it will search for \
  278.     numeric roots."
  279.  
  280. GetShiftFactor::usage =
  281.     "GetShiftFactor[expr, x] returns a list containing the common \
  282.     shift factor in the variable x and a normalized version of expr. \
  283.     For example, GetShiftFactor[ (2 s + 2 b + c) Exp[s + b + Pi], s] \
  284.     returns {b, 2 Exp[Pi + b + s] (b + c/2 + s)}."
  285.  
  286. GetStateField::usage =
  287.     "GetStateField[state, field] returns the value of the slot \
  288.     field n the list state."
  289.  
  290. GetVariables::usage =
  291.     "GetVariables[expr] returns a list of all of the variables in \
  292.     the expression expr. \
  293.     See VariableQ for the definition of a variable."
  294.  
  295. GetValue::usage =
  296.     "GetValue[f[n], n, n0] finds the numeric value of f[n] at n = n0 \
  297.     and GetValue[f[n1,n2], {n1,n2}, {n01, n02}] finds the numeric \
  298.     value of f[n1,n2] at n1 = n01 and n2 = n02. \
  299.     When the first argument has the variables embedded in it, \
  300.     two arguments are sometimes enough:  GetValue[ object, n0 ]. \
  301.     This is true when the object is an abstract signal."
  302.  
  303. HasAttributes::usage =
  304.     "HasAttributes[symbol, attribute1, attribute2, ...] returns True \
  305.     if the evaluation of symbol is another symbol and the attributes \
  306.     to be checked are a subset of the attributes of this other symbol. \
  307.     HasAttributes[Plus, {Listable, Orderless}] would return True."
  308.  
  309. ImaginaryQ::usage =
  310.     "ImaginaryQ[z] returns True if z is a number whose real part is zero."
  311.  
  312. InRange::usage =
  313.     "InRange[a, b, c, amin, cmax, leftcompare, rightcompare] returns \
  314.     True if b in between a and c. \
  315.     The inclusiveness of the interval a to c is determined by the \
  316.     arguments leftcompare and rightcompare, each of which defaults to \
  317.     LessEqual. \
  318.     So, InRange[a, b, c] returns True if a <= b <= c. \
  319.     Non-numeric values, like Infinity, can be used for amin and cmax, \
  320.     which default to -Infinity and +Infinity, respectively."
  321.  
  322. InfinityQ::usage =
  323.     "InfinityQ[a] will return True if a is Infinity, -Infinity, \
  324.     ComplexInfinity, DirectedInfinity[], or DirectedInfinity[r]."
  325.  
  326. InformUserQ::usage =
  327.     "InformUserQ[x] returns True if the options in object x contain \
  328.     Dialogue -> All or Dialogue -> True. \
  329.     It also returns True if x is All or True."
  330.  
  331. ListQ::usage =
  332.     "ListQ[expr] gives True if expr is a List, and False otherwise."
  333.  
  334. MixedPolynomialQ::usage =
  335.     "MixedPolynomialQ[p] and MixedPolynomialQ[p,x] return \
  336.     return True if p is a polynomial in negative and positive \
  337.     (mixed) powers of x.  \
  338.     Note that rational numbers like 5/6 and 1 are polynomials. \
  339.     MixedPolynomialQ[x + x^-1, x] is True."
  340.  
  341. MyApart::usage =
  342.     "MyApart[rational_polynomial, x] decomposes the rational \
  343.     polynomial into a sum of fractions whose numerators are of \
  344.     the form (x + b)^n where b is a constant and n is an integer. \
  345.     MyApart uses GetRootList to find the roots and then calls Apart. \
  346.     MyApart[rational_polynomial, x, filter] specifies a filter \
  347.     for GetRootList: Identity for rational and N for approximate roots. \
  348.     In Mathematica 1.2, MyApart is about 25 times slower than Apart."
  349.  
  350. MyCollectAll::usage =
  351.     "MyCollectAll[ expression, var ] attempts to collect all \
  352.     subexpressions of expression in terms of var."
  353.  
  354. MyFreeQ::usage =
  355.     "MyFreeQ[expr, form], when form is not a list, yields True if no \
  356.     subexpression in expr matches form. \
  357.     If form is a list, then True is returned if expr is free of \
  358.     each element of form. \
  359.     This is similar to MyFreeQ[expr, form1, form2, ...] which expands to \
  360.     MyFreeQ[expr, form1] and MyFreeQ[expr, form2] and ...."
  361.  
  362. MyMessage::usage =
  363.     "MyMessage[message-label, return-value, arg1, arg2, ...] first calls \
  364.     Message[message-label, arg1, arg2, ...] and then returns return-value."
  365.  
  366. NullPlot::usage =
  367.     "NullPlot is a 2-d graphics object which only contains the origin."
  368.  
  369. PatternQ::usage =
  370.     "PatternQ[expr] returns True if the head of expr is Pattern."
  371.  
  372. PointwisePlot::usage =
  373.     "PointwisePlot[coordlist, text] and \
  374.     PointwisePlot[coordlist, text, multiplicitytext] \
  375.     will plot the coordinates in coordlist as text \
  376.     for 2-D and 3-D graphics. \
  377.     An optional fourth argument specifies the size of the font to use. \
  378.     For multiple occurrences of the same coordinate,\
  379.     the object multiplicitytext is displayed. \
  380.     The last two arguments are usually symbols, numbers, or \
  381.     FontForm objects."
  382.  
  383. PrintIt::usage =
  384.     "PrintIt[graphics, printer] will print out graphics on a printer. \
  385.     If the printer is not specified, the default printer is used."
  386.  
  387. ProtectIt::usage =
  388.     "ProtectIt[expr] evaluates expr. \
  389.     If it evaluates to a symbol, that symbol will be write protected. \
  390.     Rules can be written for that symbol, \
  391.     but values can no longer be assigned to it."
  392.  
  393. RationalQ::usage =
  394.     "RationalQ[m] returns True if m is a rational number. \
  395.     If m is an integer, then this function also return True, \
  396.     since the set of integers are a subset of rationals."
  397.  
  398. RationalFunctionQ::usage =
  399.     "RationalFunctionQ[f,x] returns True if expression f is of the form \
  400.     f = g(x) / h(x), where h(x) depends on x but g(x) does not have \
  401.     to depend on x. \
  402.     For example, 1 / ( x + 1 ) is a rational function \
  403.     in x but x^3 + x^2 + x / ( x + 1) is not."
  404.  
  405. RationalPolynomialQ::usage =
  406.     "RationalPolynomialQ[p] and RationalPolynomialQ[p,x] return \
  407.     True if p is a rational polynomial in x. \
  408.     Note that rational numbers like 5/6 and 1 are also \
  409.     rational polynomials."
  410.  
  411. RealQ::usage =
  412.     "RealQ[z] returns True if z is a floating-point number \
  413.     (has a head of Real), False otherwise.  See RealValuedQ."
  414.  
  415. RealValuedQ::usage =
  416.     "RealValuedQ[z] gives True if z is a number whose imaginary \
  417.     component is 0, and gives False otherwise.  See RealQ."
  418.  
  419. RemoveOptions::usage =
  420.     "RemoveOptions[optionlist, options] removes the options \
  421.     from optionlist."
  422.  
  423. ReplaceWith::usage =
  424.     "ReplaceWith[oldexpr, newexpr] is a generalized way to specify \
  425.     a substitution when the substitution may be either atomic \
  426.     and a list of substitutions."
  427.  
  428. RuleAppliesQ::usage =
  429.     "RuleAppliesQ[expr, rule] returns True if rule applies to expr. \
  430.     RuleAppliesQ[head[expr1, expr2, ..., exprn], rule, head] returns \
  431.     True if the rule applies to each expression expr1, expr2, ..., \
  432.     exprn."
  433.  
  434. SameFormQ::usage =
  435.     "SameFormQ[pattern, expr1, expr2, ...] returns True if every \
  436.     expression matches pattern via MatchQ. \
  437.     Once an expression does not match, \
  438.     this function immediately returns False."
  439.  
  440. Second::usage =
  441.     "Second[list] returns the second element of list."
  442.  
  443. SetExclusion::usage =
  444.     "SetExclusion[set1, set2, ...] returns a set equal to the union \
  445.     of the sets minus the intersection of the sets."
  446.  
  447. SetStateField::usage =
  448.     "SetStateField[state, field, value] will return a new state, \
  449.     which is a copy of the list state except that the value of \
  450.     the slot field will be equal to value."
  451.  
  452. SPfunctions::usage =
  453.     "SPfunctions maintains a current list of those new routines \
  454.     that have been loaded from the signal processing packages."
  455.  
  456. SPLessGreaterRules::usage =
  457.     "SPLessGreaterRules are a collection of rules for simplifying \
  458.     expressions involving inequalities."
  459.  
  460. SPoperators::usage =
  461.     "SPoperators maintains a current list of the new mathematical \
  462.     operators that have been loaded from the signal processing packages."
  463.  
  464. SPsignals::usage =
  465.     "SPsignals maintains a current list of those new signals \
  466.     (mathematical functions) that have been loaded from the \
  467.     signal processing packages."
  468.  
  469. SPSimplificationRules::usage =
  470.     "SPSimplificationRules are a collection of simplification rules \
  471.     that are not carried out by Simplify. \
  472.     These rules require too much overhead to encode them directly \
  473.     into Mathematica. \
  474.     See also SPSimplify."
  475.  
  476. StripPackage::usage =
  477.     "StripPackage[symbol] returns the symbol (as a string) after its \
  478.     context has been removed. \
  479.     To remove the package definition from every symbol in expression, \
  480.     use MapAll[StripPackaage, expression]."
  481.  
  482. SubsetQ::usage =
  483.     "SubsetQ[set1, set2, set3,  ...] returns True if set1 is a subset \
  484.     of set2 and set2 is a subset of set3, etc."
  485.  
  486. TableLookup::usage =
  487.     "TableLookup[index, hlist, len, val] returns hlist[[index]] \
  488.     if index is between 1 and len, inclusive; otherwise, val is \
  489.     returned."
  490.  
  491. Third::usage =
  492.     "Third[list] returns the third element of list."
  493.  
  494. ToCollection::usage =
  495.     "ToCollection[expr] strips the head off of arg and returns \
  496.     the argument of expr as a collection. \
  497.     ToCollection returns an object that is a sequence, \
  498.     which is represented in Mathematica 1.2 as (a1, a2, ...) \
  499.     and in Mathematica 2.0 as Sequence[a1, a2, ...]. \
  500.     So, it provides a unified way of generating collections (sequences)."
  501.  
  502. ToList::usage =
  503.     "ToList[arg] returns arg if arg is a list. \
  504.     Otherwise, List[arg] is returned. \
  505.     ToList[arg1, arg2, ...] returns List[arg1, arg2, ...]."
  506.  
  507. UnprotectIt::usage =
  508.     "UnprotectIt[expr] evaluates expr. \
  509.     If it evaluates to a symbol, \
  510.     write protection will be removed for that symbol."
  511.  
  512. VariableQ::usage =
  513.     "VariableQ[x] returns True if x is a symbol that \
  514.     (1) does not have a numerical value associated with it and
  515.     (2) does not have its Constant attribute enabled. \
  516.     Pi fails the first test, so it is not considered a variable. \
  517.     A variable can also have the form of C[n] where n is an integer \
  518.     and C is a symbol whose Constant attribute is enabled."
  519.  
  520. ZeroQ::usage =
  521.     "ZeroQ[x] returns True if x is 0 or 0.0"
  522.  
  523. ZPolynomial::usage =
  524.     "ZPolynomial[m, n] is an mth order polynomial in the discrete \
  525.     variable n defined by the product of (-n - k) for k = 0 ... m-1. \
  526.     The z-transform of the product of this polynomial and some function \
  527.     f[n] gives z^m times the mth derivative of F(z)."
  528.  
  529. (*  E N D     U S A G E     I N F O R M A T I O N  *)
  530.  
  531.  
  532. Begin["`Private`"]
  533.  
  534.  
  535. (*  A L T E R     E X I S T I N G    F U N C T I O N S  *)
  536.  
  537. (*  And     *)
  538. Unprotect[And]
  539. And/: Simplify[And[a1_, args__]] := Apply[And, Union[{a1, args}]]
  540. Protect[And]
  541.  
  542. (*  ClearAttributes  *)
  543. Unprotect[ClearAttributes]
  544. SetAttributes[ClearAttributes, HoldFirst]
  545. Protect[ClearAttributes]
  546.  
  547. (*  Det     *)
  548. Unprotect[Det]
  549. Det[x_?NumberQ] := x
  550. Protect[Det]
  551.  
  552. (*  Dot     *)
  553. Unprotect[Dot]
  554. Dot[x_?NumberQ, y_?NumberQ] := x y
  555. Protect[Dot]
  556.  
  557. (*  Limit  *)
  558. If [ TrueQ[ $VersionNumber >= 2.0 ],
  559.      Unprotect[ Limit ];
  560.      Limit/: Options[Limit] := { Analytic -> True, Direction -> Automatic };
  561.      Protect[ Limit ] ]
  562.  
  563. (*  SetAttributes  *)
  564. Unprotect[SetAttributes]
  565. SetAttributes[SetAttributes, HoldFirst]
  566. Protect[SetAttributes]
  567.  
  568. (*  TeXForm  *)
  569. Unprotect[Re, Im]
  570. Im/: Format[ Im[x_], TeXForm ] := StringForm["\\Im{m}(``)", x]
  571. Re/: Format[ Re[x_], TeXForm ] := StringForm["\\Re{e}(``)", x]
  572. Protect[Re, Im]
  573.  
  574.  
  575.  
  576. (*  S I M P L I F I C A T I O N     R U L E S  *)
  577.  
  578. (*  PositiveOrNegative  *)
  579. PositiveOrNegative[a_] := SameQ[Head[N[a]], Real]
  580.  
  581. (*  For minimum/maximum operations  *)
  582. MinMaxRules = {
  583.     Min[t1_, t2_, rest___] :> Min[t1, rest] /; N[t1 < t2],
  584.     Min[t1_, t2_, rest___] :> Min[t2, rest] /; N[t1 > t2],
  585.     Max[t1_, t2_, rest___] :> Max[t1, rest] /; N[t1 > t2],
  586.     Max[t1_, t2_, rest___] :> Max[t2, rest] /; N[t1 < t2],
  587.  
  588.     Min[a_. + b_, c_. + b_, rest___] :> Min[a + b, rest] /; N[a < c],
  589.     Min[a_. + b_, c_. + b_, rest___] :> Min[c + b, rest] /; N[a > c],
  590.     Max[a_. + b_, c_. + b_, rest___] :> Max[c + b, rest] /; N[a < c],
  591.     Max[a_. + b_, c_. + b_, rest___] :> Max[a + b, rest] /; N[a > c]
  592. }
  593.  
  594. If [ ! TrueQ[ $VersionNumber >= 2.0 ],        (* built into 2.0's Simplify *)
  595.      MinMaxRules = MinMaxRules ~Join~ {
  596.     Min[a_, a_] :> a,
  597.     Max[a_, a_] :> a
  598.     } ]
  599.  
  600. (*  For the less than operation  *)
  601. LessRules = {
  602.     Less[Max[a_, b__], a_] :> Less[Max[b], a],
  603.     LessEqual[Max[a_, b__], a_] :> LessEqual[Max[b], a],
  604.     Less[Times[-1, b_], 0] :> Greater[b, 0],
  605.     LessEqual[Times[-1, b_], 0] :> GreaterEqual[b, 0]
  606. }
  607.  
  608. (*  For the greater than operation  *)
  609. GreaterRules = {
  610.     Greater[Min[a_, b__], a_] :> Greater[Min[b], a],
  611.     GreaterEqual[Min[a_, b__], a_] :> GreaterEqual[Min[b], a],
  612.     Greater[Times[-1, b_], 0] :> Less[b, 0],
  613.     GreaterEqual[Times[-1, b_], 0] :> LessEqual[b, 0]
  614. }
  615.  
  616. (*  For the absolute value operation  *)
  617. AbsRules = {
  618.     Abs[- a_] :> Abs[a],
  619.     Abs[x_?PositiveOrNegative y_] :> Abs[x] Abs[y],
  620.     Abs[x_]^n_. Abs[y_]^m_. :> 1 /; SameQ[x^n, y^(-m)]
  621. }
  622.  
  623. If [ ! TrueQ[ $VersionNumber >= 2.0 ],        (* built into 2.0's Simplify *)
  624.      AbsRules = AbsRules ~Join~ {
  625.     Re[Abs[a_]] :> Abs[a],
  626.     Im[Abs[a_]] :> 0,
  627.     Abs[Abs[a_]] :> Abs[a],
  628.     Abs[r_. Exp[ Complex[0, b_] a_. ] ] :> r /; PositiveOrNegative[a b r],
  629.     Abs[a_] :> a /; Positive[a],
  630.     Abs[a_] :> -a /; Negative[a]
  631.     } ]
  632.  
  633. (*  For the real and imaginary operations  *)
  634. ReImRules = {
  635.     Re[- a_] :> - Re[a],
  636.     Im[- a_] :> - Im[a],
  637.     Conjugate[ Exp[ Complex[0, b_] a_. ] ] :> Exp[ Complex[0, -b] a ] /;
  638.         PositiveOrNegative[a b],
  639.         Conjugate[ ( a_. Conjugate[z_]^r_. + b_. )^s_. ] :>
  640.         ( a z^r + b )^s /;
  641.         ((r == 1) || (r == -1)) && ((s == 1) || (s == -1)) &&
  642.         PositiveOrNegative[a] && PositiveOrNegative[b],
  643.         Conjugate[a_ b_] :> Conjugate[a] Conjugate[b]
  644. }
  645.  
  646. If [ ! TrueQ[ $VersionNumber >= 2.0 ],        (* built into 2.0's Simplify *)
  647.      ReImRules = ReImRules ~Join~ {
  648.     Re[a_] :> a /; PositiveOrNegative[a],
  649.     Im[a_] :> 0 /; PositiveOrNegative[a],
  650.  
  651.     Re[r_. Exp[ Complex[0, b_] a_. ] ] :> r Cos[b a] /;
  652.         PositiveOrNegative[a b r],
  653.     Im[r_. Exp[ Complex[0, b_] a_. ] ] :> r Sin[b a] /;
  654.         PositiveOrNegative[a b r],
  655.  
  656.     Re[Im[a_]] :> Im[a],
  657.     Im[Re[a_]] :> 0,
  658.     Re[Re[a_]] :> Re[a],
  659.     Im[Im[a_]] :> 0,
  660.  
  661.     Conjugate[Conjugate[x_]] :> x,
  662.     Conjugate[Re[x]] :> Re[x],
  663.     Conjugate[Im[x]] :> Im[x],
  664.     Conjugate[x_] :> x /; PositiveOrNegative[x]
  665.     } ]
  666.  
  667. (*  For products of exponentials  *)
  668. TimesRules = {
  669.     a_^k_ b_^k_ :> 1 /; ( a == 1/b ) && PositiveOrNegative[k]
  670. }
  671.  
  672. (*  For exponential and logarithmic functions  *)
  673. ExpLogRules = {
  674.     base_^(c_. Log[base_, b_]) :> b^c,
  675.     Log[c_. Exp[b_]] :> Log[c] + b,
  676.     Log[base_, c_. base_^b_] :> Log[base, c] + b
  677. }
  678.  
  679. If [ ! TrueQ[ $VersionNumber >= 2.0 ],        (* built into 2.0's Simplify *)
  680.      ExpLogRules = ExpLogRules ~Join~ {
  681.     Exp[c_. Log[b_]] :> b^c,
  682.     Erf[-a_] :> -Erf[a],
  683.     Exp[ a_. Complex[0, b_] Pi ] :> Exp[ Mod[a b, 2] I Pi ] /;
  684.         RationalQ[a b] && ( (a b < 0) || (a b >= 2) )
  685.     } ]
  686.  
  687. (*  Evenness and oddness of functions  *)
  688. EvenOddRules = {
  689.     Sign[-x_] :> -Sign[x],
  690.     BesselI[n_Integer, -x_] :> (-1)^n BesselI[n, x],
  691.     BesselJ[n_Integer, -x_] :> (-1)^n BesselJ[n, x]
  692. }
  693. If [ ! TrueQ[ $VersionNumber >= 2.0 ],
  694.      EvenOddRules = EvenOddRules ~Join~ {
  695.     Sin[-x_]  :> -Sin[x],
  696.     Cos[-x_]  :>  Cos[x],
  697.     Tan[-x_]  :> -Tan[x] } ]
  698.  
  699. (*  For other simplifications  *)
  700. If [ TrueQ[ $VersionNumber >= 2.0 ],
  701.      OtherRules = {
  702.     ( ((x_^l_.) t_)^k_ :> x^(l k) t^k /;
  703.         PositiveOrNegative[x] && PositiveOrNegative[l] &&
  704.         PositiveOrNegative[k] ) },
  705.      OtherRules = {
  706.     Sqrt[x_] :> I Sqrt[-x] /; x < 0,
  707.     Tan[Complex[0, b_] w_.] :> I Tanh[b w],
  708.     Sin[Complex[0, b_] w_.] :> I Sinh[b w],
  709.     Cos[Complex[0, b_] w_.] :> Cosh[b w] } ]
  710.  
  711.  
  712. SPSimplificationRules =
  713.     Join[MinMaxRules, AbsRules, TimesRules, ReImRules,
  714.          ExpLogRules, OtherRules, EvenOddRules]
  715.  
  716. SPLessGreaterRules = Join[LessRules, GreaterRules]
  717.  
  718.  
  719. (*  M E S S A G E S  *)
  720.  
  721. PointwisePlot::invalid = "Null coordinate list passed."
  722.  
  723. Dialogue::notvalid =
  724.     "The Dialogue option must be True, False, or All: `` is not valid."
  725.  
  726.  
  727. (*  G L O B A L S  *)
  728.  
  729. NullPlot := Graphics [ PointSize[0.007] ]
  730. (*  NullPlot := Graphics [ Point[{0, 0}], DisplayFunction -> Identity ]  *)
  731.  
  732.  
  733. (*  F U N C T I O N S  *)
  734.  
  735. (*  AllSubsets  *)
  736. AllSubsets[x_List] :=
  737.     Sort[ Map[Flatten, Distribute[Map[{{},{#1}}&, x], List]] ]
  738.  
  739. (*  Arrow2D  *)
  740. Arrow2D[tail_, plotwidth_, plotheight_:1] :=
  741.     Arrow2D[tail, plotwidth, plotheight, plotheight]
  742.  
  743. Arrow2D[tail_, plotwidth_, plotheight_, length_?ImaginaryQ] :=
  744.     Arrow2D[tail, plotwidth, plotheight, Im[length], Dashing[{0.02,0.02}]]
  745.  
  746. Arrow2D[tail_, plotwidth_, plotheight_, length_, style___] :=
  747.     Block [    {arrowhead, arrowleft, arrowright, head, xoffset, yoffset},
  748.         xoffset = 0.02 plotwidth;
  749.         yoffset = 0.1 (Re[plotheight] + Abs[length]) Sign[length];
  750.         head = tail + { 0, length };
  751.         arrowleft = head + { - xoffset, - yoffset };
  752.         arrowright = head + { xoffset, - yoffset };
  753.         arrowhead = head + { 0, - yoffset };
  754.         Graphics[ { Thickness[0.006],
  755.                 Line[{head, arrowleft, arrowright, head}],
  756.                 style,
  757.                 Line[{tail, arrowhead}] } ] ]
  758.  
  759. (*  AssociateItem  *)
  760. AssociateItem[item_, lookuptable_, assoctable_] :=
  761.     Map[Function[var, AssociateItem[var, lookuptable, assoctable]], item] /;
  762.     ListQ[item]
  763. AssociateItem[item_, lookuptable_, assoctable_] :=
  764.     If [ MemberQ[lookuptable, item],
  765.          assoctable [[ ToCollection[ToCollection[Position[lookuptable, item] ]] ]] ] /;
  766.     ! ListQ[item]
  767.  
  768. (*  Assuming  *)
  769. AssumingList = {}
  770.  
  771. Assuming[] := AssumingList = {}
  772. Assuming[All] := Apply[And, AssumingList]
  773. Assuming[True] := Null
  774. Assuming[True, x_] := Null
  775. Assuming[cond_] := AppendTo[AssumingList, cond]
  776. Assuming[cond_, op_List] := Assuming[cond, SameQ[Replace[Dialogue, op], All]]
  777. Assuming[cond_, True] :=
  778.     Block [    {},
  779.         Print[ "assuming ", cond ]; 
  780.         Assuming[cond] ]
  781. Assuming[cond_, x_] := Assuming[cond]
  782.  
  783. (*  CirclePS  *)
  784. CirclePS[r_] := Graphics[ Circle[{0, 0}, r] ]
  785. CirclePS[r_, p_] := Graphics[ { p, Circle[{0, 0}, r] } ]
  786.  
  787. (*  Combine  *)
  788. SetAttributes[Combine, {HoldFirst}]
  789. Combine[object_, joindata_] :=
  790.     If [ ValueQ[object],
  791.          object = Sort[object ~Join~ joindata],
  792.          object = joindata ]
  793.  
  794. (*  ComplexQ  *)
  795. ComplexQ[z_] := NumberQ[z] && SameQ[Head[z], Complex]
  796.  
  797. (*  ComplexTo2DCoord and ComplexTo2DCoordList  *)
  798. ComplexTo2DCoord[z_] := { Re[z], Im[z] }
  799.   
  800. ComplexTo2DCoordList[zlist_] := Map[ ComplexTo2DCoord, zlist ]
  801.  
  802. (*  ConstantQ  *)
  803. ConstantQ[x_?AtomQ] := NumberQ[x] || HasAttributes[x, Constant]
  804. ConstantQ[f_[x__]] := Apply[And, Map[ConstantQ, List[x]]]
  805.  
  806. (*  ConstantTerm  *)
  807. ConstantTerm[expr_, z_:Global`x] :=
  808.     Block [ {nonpropterms},
  809.         keepconstants[e_] := If [ MyFreeQ[e,z], e, 0 ];
  810.         nonpropterms = Coefficient[expr, z, 0];
  811.         If [ MyFreeQ[nonpropterms, z],
  812.              nonpropterms,
  813.              Map[keepconstants, nonpropterms] ] ]
  814.  
  815. (*  Element  *)
  816. properIndex[i_Integer] := True
  817. properIndex[i_List] := Apply[And, Map[IntegerQ, Flatten[i]]]
  818. properIndex[i___] := properIndex[ {i} ]
  819.  
  820. Element[h_[args__], i___] := h[args] [[i]] /; properIndex[i]
  821.  
  822. (*  EmptyQ  *)
  823. EmptyQ[x_?AtomQ] := False
  824. EmptyQ[h_[]] := True
  825. EmptyQ[h_[values__]] := False
  826.  
  827. (*  GenerateCode  *)
  828. GenerateCode[code_] := ToExpression[ToString[code]]
  829.  
  830. (*  GeneratePattern  *)
  831. GeneratePattern[name_] := GenerateSymbol[name, "_"]
  832.  
  833. (*  GenerateSymbol  *)
  834. GenerateSymbol[name_] := GenerateCode[name]
  835. GenerateSymbol[name_, trailer_] :=
  836.     GenerateCode[StringForm["````", name, trailer]]
  837. GenerateSymbol[name_, trailer_, header_] :=
  838.     GenerateCode[StringForm["``````", header, name, trailer]]
  839.  
  840. (*  GetAllShiftFactors  *)
  841. shiftFactorList = {}
  842.  
  843. addFactor[f_] := Block [ {}, AppendTo[shiftFactorList, f]; f ]
  844.  
  845. GetAllShiftFactors[expr_, s_] :=
  846.     Block [    {normexpr, rules},
  847.         shiftFactorList = {};
  848.         rules = (a_. s + b_. :> addFactor[b/a] /; FreeQ[b, s]);
  849.         If [ ! TrueQ[ $VersionNumber >= 2.0 ],
  850.              rules = { (a_. s + b__) :> addFactor[Plus[b]/a] /;
  851.                 FreeQ[ Plus[b], s ],
  852.                    rules,
  853.                    s :> addFactor[0] } ];
  854.         normexpr = expr /. rules;
  855.         shiftFactorList ]
  856.  
  857. (*  GetArgs  *)
  858. GetArgs[h_[]] := Null
  859. GetArgs[h_[x__][d__]] := d
  860. GetArgs[h_[x__]] := x
  861.  
  862. GetArgs[e1_, e__] := ToCollection[ GetArgs[e1], GetArgs[e] ]
  863.  
  864. (*  GetAllExponents and GetAllFactors  *)
  865. depthfirstsearch[expr_, lhs_, rule_] :=
  866.     Block [ {cur, i, len, newexpr},
  867.  
  868.         If [ ! AtomQ[expr],
  869.              len = Length[expr];
  870.              For [ i = 1, i <= len, i++,
  871.                cur = expr[[i]];
  872.                If [ MatchQ[cur, lhs],
  873.                 newexpr = Replace[cur, rule];
  874.                 If [ SameQ[cur, newexpr],
  875.                      depthfirstsearch[cur, lhs, rule],
  876.                      PrependTo[list, newexpr] ],
  877.                 depthfirstsearch[cur, lhs, rule] ] ] ];
  878.  
  879.         Null ]
  880.  
  881. depthdriver[expr_, lhs_, rule_] :=
  882.     Block [    {depthflag = True},
  883.         list = {};
  884.         If [ MatchQ[expr, lhs],           (* check top level first *)
  885.              newexpr = Replace[expr, rule];
  886.              If [ ! SameQ[expr, newexpr],
  887.                   PrependTo[list, newexpr]; depthflag = False ] ];
  888.         If [ depthflag,
  889.              depthfirstsearch[expr, lhs, rule] ];
  890.         list ]
  891.  
  892. GetAllExponents[ expr_, z_ ] :=
  893.     depthdriver[ expr,
  894.              c_. z^n_.,
  895.              c_. z^n_. :> If [ FreeQ[c, z], n, c z^n ] ]
  896.  
  897. GetAllFactors[ expr_, z_ ] :=
  898.     depthdriver[ expr,
  899.              c_. z^n_.,
  900.              c_. z^n_. :> If [ FreeQ[c, z], c^Sign[n], c z^n ] ] /.
  901.     ( Sign[x_] :> 1 )
  902.  
  903. (*  GetOperatorVariables  *)
  904. GetOperatorVariables[ h_[var_, rest___] ] := var
  905.  
  906. (*  GetRoot  *)
  907. GetRoot[{}] := {}                (* no roots *)
  908. GetRoot[rule_] := Second[First[rule]]
  909.  
  910. (*  GetRootList  *)
  911. extractRoot[ ToRules[x_] ] := N [ ToRules[x] ]    (* ToRules returns collection *)
  912. extractRoot[ y_ ] := y
  913.  
  914. goodroot[r_] := ! MatchQ[r, DirectedInfinity[___]]
  915.  
  916. GetRootList[p_, x_, filter_:N] :=
  917.     Select[ Map[ GetRoot, Map[extractRoot, filter[Solve[p == 0, x]]] ],
  918.         goodroot ]
  919.  
  920. (*  GetShiftFactor  *)
  921. commonFactor = 0
  922.  
  923. myMin[ x1_?RealValuedQ, x2_?RealValuedQ ] :=
  924.     Min[x1, x2]
  925. myMin[ x1_?RealValuedQ, Complex[re2_,im2_] ] :=
  926.     Complex[myMin[x1, re2], im2]
  927. myMin[ Complex[re1_,im1_], Complex[re2_,im2_] ] :=
  928.     Complex[myMin[re1,re2], myMin[im1,im2] ]
  929.  
  930. reduce[ 0, x_, term_ ] := term        (* stopping conditions  *)
  931. reduce[ x_, 0, term_ ] := term
  932.  
  933. reduce[ x1_?NumberQ + rest1_., x2_?NumberQ + rest2_., term_ ] :=
  934.     reduce[ rest1, rest2, term + myMin[x1,x2] ]
  935. reduce[ x1_. y_ + rest1_., x2_. y_ + rest2_., term_ ] :=
  936.     reduce[ rest1, rest2, term + myMin[x1,x2] y ] /;
  937.     NumberQ[x1] && NumberQ[x2] && ! NumberQ[y]
  938.  
  939. reduce[ a_, b_, term_ ] := term        (* incomplete reduction *)
  940.  
  941. extractShift[ a_, b_, s_ ] :=
  942.     Block [ {shift},
  943.         shift = Expand[b/a];
  944.         If [ ValueQ[commonFactor],
  945.              commonFactor = reduce[shift, commonFactor, 0],
  946.              commonFactor = shift ];
  947.         a ( s + shift ) ]
  948.  
  949. GetShiftFactor[expr_, s_] :=
  950.     Block [    {normexpr, rules},
  951.         Clear[commonFactor];
  952.         rules = (a_. s + b_. :> extractShift[a, b, s]);
  953.         If [ ! TrueQ[ $VersionNumber >= 2.0 ],
  954.              rules = { (a_. s + b__) :> extractShift[a, Plus[b], s],
  955.                    rules,
  956.                    s :> extractShift[1, 0, s] } ];
  957.         normexpr = expr /. rules;
  958.         If [ ! ValueQ[commonFactor], commonFactor = 0 ];
  959.         { commonFactor, normexpr } ]
  960.  
  961. (*  GetStateField  *)
  962. GetStateField[state_List, field_] := state[[field]]
  963.  
  964. (*  GetVariables  *)
  965. extractrules = { f_[x__][y__][z__] :> bogus[x, y, z],
  966.          f_[x__][y__] :> bogus[x, y],
  967.          (x_ -> y_) :> {},
  968.          (x_ :> y_) :> {} }
  969.  
  970. GetVariables[x_] :=
  971.     Union[ Select[ Level[x /. extractrules, Infinity], VariableQ ] ]
  972.  
  973. (*  GetValue  *)
  974. GetValue[f_, n_Symbol, n0_] :=
  975.     Block [    {value},
  976.         value = N [ f /. n -> n0 ];
  977.         If [ NumberQ[value],
  978.              value,
  979.              N [ Limit[f, n -> n0] ] ] ]
  980.  
  981. GetValue[f_, {n1_Symbol, n2_Symbol}, {n01_, n02_}] :=
  982.     Block [    {value},
  983.         value = N [ f /. { n1 -> n01, n2 -> n02 } ];
  984.         If [ NumberQ[value],
  985.              value,
  986.              N[ Limit[ Limit[f, n1 -> n01], n2 -> n02] ] ] ]
  987.  
  988. (*  HasAttributes  *)
  989. HasAttributes[symbol_, attrib1_, attribs__] :=
  990.     HasAttributes[symbol, {attrib1, attribs}]
  991.  
  992. HasAttributes[symbol_Symbol, attrib_] :=
  993.     Block [    {attributes, protected},
  994.         attributes = Attributes[Attributes];
  995.         Unprotect[Attributes];
  996.         ClearAttributes[Attributes, {HoldFirst, HoldAll, HoldRest}];
  997.         protected = If [ AtomQ[attrib],
  998.                  MemberQ[Attributes[symbol], attrib],
  999.                  SubsetQ[attrib, Attributes[symbol]] ];
  1000.         SetAttributes[Attributes, attributes];
  1001.         protected ]
  1002.  
  1003. (*  ImaginaryQ  *)
  1004. ImaginaryQ[z_] := NumberQ[z] && ZeroQ[Re[z]]
  1005.  
  1006. (*  InRange, function will be automatically threaded if a,b,c are not atoms  *)
  1007. SetAttributes[MyInRange, Listable]
  1008.  
  1009. InRange[a_, b_, c_, amin_:-Infinity, cmax_:Infinity, leftcompare_:LessEqual, rightcompare_:LessEqual ] :=
  1010.     Apply[And,
  1011.           ToList[MyInRange[a, b, c, amin, cmax, leftcompare, rightcompare]]]
  1012.  
  1013. MyInRange[a_, b_, c_, amin_, cmax_, leftcompare_, rightcompare_] :=
  1014.     Which [ SameQ[a, amin] && SameQ[c, cmax],
  1015.           True,
  1016.         SameQ[a, amin],
  1017.           SameQ[b, amin] || rightcompare[b, c],
  1018.         SameQ[c, cmax],
  1019.           SameQ[b, cmax] || leftcompare[a, b],
  1020.         True,
  1021.           leftcompare[a, b] && rightcompare[b, c] ]
  1022.  
  1023.  
  1024. (*  InfinityQ  *)
  1025. InfinityQ[e_List] := Apply[And, Map[InfinityQ, e]]
  1026. InfinityQ[DirectedInfinity[]] := True 
  1027. InfinityQ[DirectedInfinity[r_]] := True
  1028. InfinityQ[a_] := False
  1029.  
  1030. (*  InformUserQ  *)
  1031. informuser[All] := True
  1032. informuser[True] := True
  1033. informuser[False] := False
  1034. informuser[x_] := False
  1035.  
  1036. InformUserQ[x_List] := informuser[Replace[Dialogue, x]]
  1037. InformUserQ[x_] := informuser[x]
  1038.  
  1039. (*  ListQ--  it is an undocumented primitive in Mma 2.0+    *)
  1040. (*           in 2.0, it does not always return True or False    *)
  1041. ListQ[object_] := SameQ[Head[object], List]
  1042.  
  1043. (*  MixedPolynomialQ  *)
  1044. twosided[ c_. z_^r_., z_ ] := FreeQ[c, z] && IntegerQ[r]
  1045. twosided[ c_, z_ ] := FreeQ[c, z]
  1046.  
  1047. MixedPolynomialQ[c_] := MixedPolynomialQ[c, Global`x]
  1048.  
  1049. MixedPolynomialQ[x_?AtomQ, z_] := True
  1050. MixedPolynomialQ[Plus[a_, b__], z_] := Apply[And, Map[twosided[#1, z]&, {a, b}]]
  1051. MixedPolynomialQ[x_, z_] := twosided[x, z]
  1052.  
  1053. (*  MyApart --  kludge around the way Apart does partial fractions *)
  1054. (*        Root denominator and replace roots with symbols       *)
  1055. MyApart[ratpoly_, x_, filter_:Identity] :=
  1056.     Block [    {apart, denom, denomfactored,
  1057.          normfact, numer, partfrac, rootlist, rootmult, rules},
  1058.  
  1059.         numer = Numerator[ratpoly];
  1060.         denom = Denominator[ratpoly];
  1061.         normfact = Last[ CoefficientList[denom, x] ];
  1062.         numer /= normfact;
  1063.         denom /= normfact;
  1064.         rootlist = Sort[ GetRootList[denom, x, filter] ];
  1065.         { denomfactored, rules } = multiplicityform[rootlist, x];
  1066.         apart = Apart[numer / denomfactored, x];
  1067.  
  1068.         partfrac = apart /. rules;
  1069.         partfrac /. ( a_. / (b_ c_) :> a / ( Together[b] c ) /;
  1070.                 FreeQ[b, x] &&  ! FreeQ[c, x] ) ]
  1071.  
  1072. multiplicityform[ roots_, x_ ] :=
  1073.     Block [    {count = 1, cur, denom = 1, i, last,
  1074.          length, sublist = {}, sym = 1},
  1075.         Clear[localvar];    (* localvar is global to package *)
  1076.         length = Length[roots];
  1077.         last = First[roots];
  1078.         For [ i = 2, i <= length, i++,
  1079.               cur = roots[[i]];
  1080.               If [ SameQ[ cur, last ],
  1081.                count++,
  1082.                denom *= (x + localvar[sym])^count;
  1083.                  PrependTo[ sublist, localvar[sym] -> -last ];
  1084.                  sym++;
  1085.                  count = 1 ];
  1086.               last = cur ];
  1087.  
  1088.         denom *= (x + localvar[sym])^count;
  1089.         PrependTo[ sublist, localvar[sym] -> -last ];
  1090.  
  1091.         { denom, sublist } ]
  1092.  
  1093. (*  MyCollectAll  *)
  1094. MyCollectAll[ a_, x_ ] :=
  1095.     a /. ( h_ :> Collect[h, x] /; PolynomialQ[h,x] || MixedPolynomial[h,x] )
  1096.  
  1097. (*  MyFreeQ  *)
  1098. MyFreeQ[expr_, {form_}] := FreeQ[expr, form]
  1099. MyFreeQ[expr_, {form1_, forms__}] := FreeQ[expr, form1] && MyFreeQ[expr, forms]
  1100. MyFreeQ[expr_, form_] := FreeQ[expr, form]
  1101. MyFreeQ[expr_, form1_, forms__] := FreeQ[expr, form1] && MyFreeQ[expr, forms]
  1102.  
  1103. (*  MyMessage  *)
  1104. SetAttributes[MyMessage, HoldFirst]
  1105. MyMessage[message_, return_] :=
  1106.     Block [    {},
  1107.         Message[message];
  1108.         return ]
  1109. MyMessage[message_, return_, args__] :=
  1110.     Block [    {},
  1111.         Message[message, args];
  1112.         return ]
  1113.  
  1114. (*  PatternQ  *)
  1115. PatternQ[expr_] := SameQ[Head[expr], Pattern]
  1116.  
  1117. (*  PointwisePlot  *)
  1118.  
  1119. PointwisePlot[coordlist_, singtext_] :=
  1120.     PointwisePlot[coordlist, singtext, singtext]
  1121.  
  1122. (*  plots each unique set of coordinates.  multiple occurrences of the   *)
  1123. (*    same coordinate are plotted as <text>(n), where n is the number of *)
  1124. (*    occurrences.  First, the coordinate list is sorted.  A Null is     *)
  1125. (*    appended because the scanning function compares the current        *)
  1126. (*    coordinate with the last, so that Null forces the last coordinate  *)
  1127. (*    to be processed.  After the pointwiseplot graphics commands are    *)
  1128. (*    built up, the resulting plot is returned as a graphics object.     *)
  1129. (*    The point size of the text defaults to 18.  Supported font sizes   *)
  1130. (*    are 10, 12, 14, 16, 18, 20, 24, ...                 *)
  1131.  
  1132. PointwisePlot[coordlist_, singtext_, multtext_, fontsize_:18] :=
  1133.     Block [    {counter = 1, text, lastcoord = Null,
  1134.          pointwiseplot = {}, ptsize, str},
  1135.         ptsize = Round[fontsize];
  1136.         Scan [ Function[ coord,
  1137.              Which [ SameQ[lastcoord, Null],   (* initial cond.   *)
  1138.                    counter = 1;
  1139.                    lastcoord = coord,
  1140.                  SameQ[coord, lastcoord],  (* multiple occur. *)
  1141.                    ++counter,
  1142.                  True,                   (* plot it *)
  1143.                    str = If [ SameQ[counter, 1],
  1144.                              singtext,
  1145.                           multtext ];
  1146.                    text = If [ TrueQ[$VersionNumber >= 2.0],
  1147.                            FontForm[str, {"Bold", ptsize}],
  1148.                            FontForm[str, "Bold", ptsize] ];
  1149.                    AppendTo[ pointwiseplot,
  1150.                          Text[text, lastcoord] ];
  1151.                    counter = 1;
  1152.                    lastcoord = coord ] ],
  1153.                Append[Sort[coordlist], Null] ];
  1154.         Graphics[pointwiseplot] ] /;
  1155.     ! EmptyQ[coordlist]
  1156.  
  1157. PointwisePlot[coordlist_, singtext_, multtext_] :=
  1158.     MyMessage[PointwisePlot::invalid, NullPlot] /;
  1159.     EmptyQ[coordlist] 
  1160.  
  1161. (*  PrintIt  *)
  1162. PrintIt[graphics_] :=
  1163.     Display["!psfix | lpr", graphics]
  1164.  
  1165. PrintIt[graphics_, printer_] :=
  1166.     Display[ToString[StringForm["!psfix | lpr -P``", printer]], graphics]
  1167.  
  1168. (*  ProtectIt  *)
  1169. ProtectIt[symbol_Symbol] := Apply[Protect, {symbol}]
  1170.  
  1171. (*  RationalQ  *)
  1172. RationalQ[z_Integer] := True
  1173. RationalQ[z_Rational] := True
  1174. RationalQ[z_] := False
  1175.  
  1176. (*  RationalFunctionQ  *)
  1177. RationalFunctionQ[f_, x_:Global`x] :=
  1178.     ( ! SameQ[Head[f], Plus] ) && ( ! MyFreeQ[Denominator[f], x] )
  1179.  
  1180. (*  RationalPolynomialQ  *)
  1181. RationalPolynomialQ[p_] :=
  1182.     PolynomialQ[Numerator[p]] && PolynomialQ[Denominator[p]]
  1183. RationalPolynomialQ[p_, x_] :=
  1184.     PolynomialQ[Numerator[p], x] && PolynomialQ[Denominator[p], x]
  1185.  
  1186. (*  RealQ  *)
  1187. RealQ[z_] := SameQ[Head[z], Real]
  1188.  
  1189. (*  RealValuedQ  *)
  1190. RealValuedQ[z_] := NumberQ[z] && ZeroQ[Im[z]]
  1191.  
  1192. (*  RemoveOptions  *)
  1193. badOptionList = {}
  1194. goodOptionQ[ a_ -> b_ ] := ! MemberQ[badOptionList, a]
  1195. goodOptionQ[ a_ :> b_ ] := ! MemberQ[badOptionList, a]
  1196. goodOptionQ[ x_ ] := False
  1197.  
  1198. RemoveOptions[ oplist_List, badoplist_List ] :=
  1199.     Block [ {},
  1200.         badOptionList = badoplist;
  1201.         Select[ oplist, goodOptionQ ] ]
  1202.  
  1203.  
  1204. (*  ReplaceWith  *)
  1205. SetAttributes[ReplaceWith, {Listable}]
  1206. ReplaceWith[org_, val_] := org -> val
  1207.  
  1208. (*  RuleAppliesQ  *)
  1209. (*  Yes, I tried the "efficient" way of separating the lhs    *)
  1210. (*  and rhs to see if the lhs applies to an expression;        *)
  1211. (*  The would avoid the evaluation of the right-hand side.    *)
  1212. (*  The main problem is that we are not guaranteed to run    *)
  1213. (*  through all possible pattern matches since this separation    *)
  1214. (*  only considers one pattern match.  Therefore, I had to    *)
  1215. (*  encode this by evaluating the rule using Replace.        *)
  1216.  
  1217. RuleAppliesQ[expr_, rule_] := ! SameQ[expr, Replace[expr, rule]]
  1218. RuleAppliesQ[expr_, rule_, True] :=
  1219.     Apply[ And, Map[ RuleAppliesQ[#, rule]&, Apply[List, expr] ] ]
  1220.  
  1221. (*  SameFormQ  *)
  1222. SameFormQ[form_, expr_] := MatchQ[expr, form]
  1223. SameFormQ[form_, expr1_, expr__] :=
  1224.     SameFormQ[form, expr1] && SameFormQ[form, expr]
  1225.  
  1226. (*  Second  *)
  1227. Unprotect[Second]
  1228. Second[x_] := x[[2]]
  1229. Protect[Second]
  1230.  
  1231. (*  SetExclusion  *)
  1232. SetExclusion[sets__] := Complement[Union[sets], Intersection[sets]]
  1233.  
  1234. (*  SetStateField  *)
  1235. SetStateField[state_List, field_, value_] :=
  1236.     Block [ {newstate},
  1237.         newstate = state;
  1238.         newstate[[field]] = value;
  1239.         newstate ]
  1240.  
  1241. (*  StripPackage  *)
  1242. StripPackage[symbol_Symbol] := StripPackage[ ToString[symbol] ]
  1243.  
  1244. StripPackage[symbol_String] :=
  1245.     Block [    {expandedstring, pos},
  1246.         expandedstring = Characters[symbol];
  1247.         pos = Position[expandedstring, "`"];
  1248.         If [ SameQ[pos, {}],
  1249.              symbol,
  1250.              Apply[ StringJoin,
  1251.                 Drop[expandedstring, Last[Last[pos]]] ] ] ]
  1252.  
  1253. StripPackage[x_] := x
  1254.  
  1255. (*  SubsetQ  *)
  1256. SubsetQ[x1_] := True
  1257. SubsetQ[x1_, x2_] :=
  1258.     Block [    {x1sorted},
  1259.         x1sorted = Sort[x1];
  1260.         SameQ[x1sorted, Intersection[x1sorted, x2]] ]
  1261. SubsetQ[x1_, x2_, x__] := SubsetQ[x1, x2] && SubsetQ[x2, x]
  1262.  
  1263. (*  TableLookup  *)
  1264. TableLookup[index_, table_, len_, val_] :=        (* multidimensional *)
  1265.     Which [ TrueQ[ Apply[Or, Map[InfinityQ, index]] ],
  1266.           val,
  1267.         TrueQ[ InRange[1, index, len] ],
  1268.           Apply[Part, {table} ~Join~ index],
  1269.         True,
  1270.           val ] /;
  1271.     ListQ[index]
  1272.  
  1273. TableLookup[index_, table_, len_, val_] :=        (* one-dimensional  *)
  1274.     Which [ InfinityQ[index],
  1275.           val,
  1276.         TrueQ[ 1 <= index <= len ],
  1277.           table[[index]],
  1278.         True,
  1279.           val ] /;
  1280.     ( InfinityQ[index] || IntegerQ[index] ) && IntegerQ[len]
  1281.  
  1282. (*  Third  *)
  1283. Third[x_] := x[[3]]
  1284.  
  1285. (*  ToCollection  *)
  1286. ToCollection[x_?AtomQ] := x
  1287. ToCollection[h_[args___]] := args
  1288. ToCollection[a__] := a
  1289.  
  1290. (*  ToList  *)
  1291. ToList[] := {}
  1292. ToList[arg_List] := arg
  1293. ToList[arg_] := List[arg] /; ! SameQ[Head[arg], List]
  1294. ToList[arg1_, args__] := List[arg1, args]
  1295.  
  1296. (*  UnprotectIt  *)
  1297. UnprotectIt[symbol_Symbol] :=
  1298.     Block [    {attributes},
  1299.         attributes = Attributes[Unprotect];
  1300.         Unprotect[Unprotect];
  1301.         ClearAttributes[Unprotect, {HoldFirst, HoldAll, HoldRest}];
  1302.         Unprotect[symbol];
  1303.         SetAttributes[Unprotect, attributes] ]
  1304.  
  1305. (*  VariableQ  *)
  1306. VariableQ[x_Symbol] := ! ConstantQ[x]
  1307. VariableQ[x_[n_Integer]] := HasAttributes[x, Constant]
  1308. VariableQ[x_] := False
  1309.  
  1310. (*  ZeroQ  *)
  1311. ZeroQ[x_] := SameQ[x, 0] || SameQ[x, 0.0]
  1312.  
  1313. (*  ZPolynomial  *)
  1314. ZPolynomial[m_Integer, n_] :=
  1315.     (-1)^m Expand[ Product[n + k, {k, 0, m-1}] ] /; ( m > 0 )
  1316.  
  1317.  
  1318. (*  E N D     P A C K A G E *)
  1319.  
  1320. End[]
  1321. EndPackage[]
  1322.  
  1323.  
  1324. If [ TrueQ[ $VersionNumber >= 2.0 ],
  1325.      On[ Set::wrsym ];
  1326.      On[ SetDelayed::write ];
  1327.      On[ General::spell ];
  1328.      On[ General::spell1 ] ]
  1329.  
  1330.  
  1331. (*  H E L P     I N F O R M A T I O N  *)
  1332.  
  1333. Block [    {newfuns},
  1334.     newfuns =
  1335.     { AllSubsets,        Assuming,        CirclePS,
  1336.       Combine,        ComplexQ,        ComplexTo2DCoord,
  1337.       ComplexTo2DCoordList,    ConstantQ,        ConstantTerm,
  1338.       Element,        GenerateCode,        GeneratePattern,
  1339.       GenerateSymbol,    GetAllExponents,    GetAllFactors,
  1340.       GetAllShiftFactors,    GetArgs,        GetRoot,
  1341.       GetRootList,        GetShiftFactor,        GetStateField,
  1342.       GetValue,        GetVariables,        ImaginaryQ,
  1343.       InRange,        InfinityQ,        InformUserQ,
  1344.       ListQ,        MixedPolynomialQ,    MyApart,
  1345.       MyCollectAll,        MyFreeQ,        MyMessage,
  1346.       PointwisePlot,    PrintIt,        RationalFunctionQ,
  1347.       RationalPolynomialQ,    RationalQ,        RealQ,
  1348.       RealValuedQ,        RemoveOptions,        ReplaceWith,
  1349.       RuleAppliesQ,        SameFormQ,        Second,
  1350.       SetExclusion,        SetStateField,        StripPackage,
  1351.       SubsetQ,        TableLookup,        Third,
  1352.       ToCollection,        ToList,            VariableQ,
  1353.       ZeroQ,        ZPolynomial };
  1354.     SPfunctions = Combine[SPfunctions, newfuns];    
  1355.     Apply[Protect, newfuns];
  1356.     Protect[Dialogue] ]
  1357.  
  1358. Protect[ SPSimplificationRules ]
  1359.  
  1360.  
  1361. (*  E N D I N G     M E S S A G E  *)
  1362.  
  1363. If [ ! $loaded, Print["Support module has been loaded."] ]
  1364. Remove[ $loaded ]
  1365.